package ClassificationAlgorithmUtil;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import Definitions.GraphClass;
import Definitions.NodeClass;
import FeatureSelection.FeatureSelectionmRMRClass;
import Global.GlobalClass;
import Result.ResultClass;
import Sampling.SamplingAbstractClass;
import Utility.FileUtilityClass;

public class CCAUtil {

	/***
	 * content 
	 * 
	 * @param graph
	 */

	public static void discretizeMatrix(double[][] X)
	{
		FeatureSelectionmRMRClass.discretizeMatrix(X, 0.42);
		
		for(int i=0 ; i<X.length ; i++)
		{
			for(int j =0 ; j< X[0].length ; j++)
			{
				// make a take values 0,1,2 instead of -1,0,1
				double a = (X[i][j] * 2 + 2) /2;
				X[i][j] = a;
			}
		}
	}
	
	public static double [][] discretizData(GraphClass graph)
	{
		double X[][] = new double [graph.getDataSet().size()][graph.getDataSet().get(0).getContent(0).size()];
		
		for(int i=0 ; i<graph.getDataSet().size() ; i++)
		{
			ArrayList<Double> attributes =graph.getDataSet().get(i).getContentList().get(0).getAttributeList();
			
			for(int j =0 ; j< attributes.size() ; j++)
			{
				X[i][j] = attributes.get(j);
			}
		}

		discretizeMatrix(X);
		return X;
	}
	
	/**
	 * 
	 * @param currentSampling related sampling 
	 * @param nodeList list of aray nodes  
	 * @return accuracy results of accuracy for nodelist in current sampling
	 */
	public static double findAccuracy(SamplingAbstractClass currentSampling, List<NodeClass> nodeList)
	{
		int accuracy = 0;
		
		for(NodeClass u: nodeList)
		{
			if( currentSampling.getClassLabelEstimated(u)  == u.getClassOrder())
			{
				accuracy++;
			}
		}
		
		return ((double)accuracy/(double)nodeList.size());
	}


	/***
	 * 
	 * @param currentSampling
	 * @param nodelist
	 * @param size
	 * @return
	 */
	public static int[][]  CreateConfMat(SamplingAbstractClass currentSampling,ArrayList <NodeClass> nodelist, int size) 
	{
		int classSize=size;
		int[][] confMat = new int [classSize][classSize];
		
		for(int i= 0; i<classSize ; i++)
		{
			for(int j= 0; j<classSize ; j++)
			{
				confMat[i][j] = 0;
			}
		}		
		
		for(NodeClass node : nodelist)
		{
			int m=  currentSampling.getClassLabelEstimated(node);
			int k=  node.getClassOrder();
			
			if(m<0)
			{
				System.out.println("ERROR:There are class labels still not estimated");
				System.exit(0);
			}		
			
			confMat [k][m]++;	
		}
		
		//printConfusionMatrix();
		return confMat;
	}

	

	public static void writeFile(String info, String name, float iterationTestAccuracyResult[][], double testAcc, double[] clas) throws IOException
	{
		
		FileWriter fstream = new FileWriter(name);
		BufferedWriter out = new BufferedWriter(fstream);
		out.newLine();
		out.write(info);
		out.newLine();
		out.write("%UnlabeledSize TrainAccuracy  TestAccuracy TestAccClassifier1.....TestAccClassifierN TestConfMat11.....TestConfMatCC%");
		out.newLine();
		FileUtilityClass.WriteMatrixToFile(iterationTestAccuracyResult,out);
		out.newLine();
		out.write("Result: "+ testAcc);
		out.newLine();			
		for(double d: clas)
		{
			out.write(d+"  "); 
		}
		out.close();
	}

	

	/**
	 * This method reports Results of CCA Algorithm to file. 
	 * @param results is the results or CCA algorithm.
	 */
	public static void Report(ResultClass results)
	{
		
	}
	
	public static void WriteIterationResultsToFile(GlobalClass global,String fileName, ArrayList <Float> iterationTestAccuracyResult,double[] accuracy) throws IOException
   {    		FileWriter fstream = new FileWriter(fileName);    		BufferedWriter out = new BufferedWriter(fstream);        		out.write("Iteration Results");    		out.newLine();    		    		for(float f:iterationTestAccuracyResult)    		{    			out.write("Acc : "+f);     			out.newLine();    		}    		out.write("%Class Based Accuracy Results");    		out.newLine();    		    		for(int j=0 ; j<global.classList.size() ;j++)    		{    			out.write("%"+j+"  "+ accuracy[j]);    			out.newLine();    		}    		    		out.close();    }    	
} 